﻿using NewsReader.Helpers;
using NewsReader.Log;
using NewsReader.ViewModels;
using NewsReaderApp.Views;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

namespace NewsReaderApp.ViewModels
{
    internal sealed class FeedSelectionVM
    {
        private readonly ObservableCollection<object> _feeds = new ObservableCollection<object>();
        private readonly ObservableCollection<object> _selectedFeeds = new ObservableCollection<object>();
        private readonly CollectionViewSource _feedsByCat;
        private readonly DelegateCommand _saveAndContinueCommand;
        private readonly DelegateCommand _cancelCommand;
        private bool _selectionAdded;
        private bool _selectionRemoved;

        public event EventHandler FeedSelectionCompleted;

        public FeedSelectionVM(CollectionViewSource cvs)
        {
            _saveAndContinueCommand = new DelegateCommand(o => SaveSelectedAndContinue(),
                                           o => _selectedFeeds.Count > 0);

            _cancelCommand = new DelegateCommand(o => Cancel(),
                                                 o => _selectedFeeds.Count > 0);
            _feedsByCat = cvs;
            _selectedFeeds.CollectionChanged += HandleSelectionChanged;
            LoadFeeds().ContinueWith(t =>
                {
                    if (t.IsFaulted)
                    {
                        Logger.Log.ErrorFormat("LoadFeeds() failed. Exception {0}", t.Exception);
                    }

                });
        }
        private void Cancel()
        {
            RequestHideView();
        }

        private async void SaveSelectedAndContinue()
        {
            try
            {
                await PersistenceHelper.SaveUserSelectedFeedsAsync(_selectedFeeds.OfType<UserFeedConfig>());

                RequestHideView();
            }
            catch (Exception ex)
            {
                Logger.Log.ErrorFormat("SaveSelectedAndContinue() failed. Exception {0}", ex);
            }
        }

        private void RequestHideView()
        {
            if (FeedSelectionCompleted != null)
            {
                FeedSelectionCompleted(this, EventArgs.Empty);
            }
        }

        private void HandleSelectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
            {
                _selectionAdded = true;
                foreach (UserFeedConfig ufc in e.NewItems)
                {
                    ufc.IsSelected = true;
                }
            }
            else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
            {
                _selectionRemoved = true;
                foreach (UserFeedConfig ufc in e.OldItems)
                {
                    ufc.IsSelected = false;
                }
            }

            _saveAndContinueCommand.RaiseCanExecuteChanged();
            _cancelCommand.RaiseCanExecuteChanged();
        }

        public bool SelectionAdded
        {
            get { return _selectionAdded; }
        }

        public bool SelectionRemoved
        {
            get { return _selectionRemoved; }
        }

        public void ResetSelection()
        {
            _selectionAdded = false;
            _selectionRemoved = false;
        }

        public IEnumerable<object> AllFeeds
        {
            get { return _feeds; }
        }

        public ObservableCollection<object> SelectedFeeds
        {
            get { return _selectedFeeds; }
        }

        private async Task LoadFeeds()
        {
            var cannedFeed = await PersistenceHelper.GetCannedFeedsAsync();
            var userFeeds = (await PersistenceHelper.GetUserFeedsAsync()).ToDictionary(f => f.Uri);

            var tobeSelected = new List<UserFeedConfig>();

            foreach(var feed in cannedFeed)
            {
                bool userSelected = userFeeds.ContainsKey(feed.Uri);
                var ufc = new UserFeedConfig(feed, userSelected);
                _feeds.Add(ufc);
                if (userSelected)
                {
                    tobeSelected.Add(ufc);
                }
                userFeeds.Remove(feed.Uri);
            }

            foreach (var feed in userFeeds.Values)
            {
                var ufc = new UserFeedConfig(feed, true);
                ufc.Category = "User-Defined";
                _feeds.Add(ufc);
                tobeSelected.Add(ufc); 
            }

            _feedsByCat.Source = _feeds.GroupBy(o => ((UserFeedConfig)o).Category).OrderBy(g => g.Key);

            foreach(var f in tobeSelected)
            {
                _selectedFeeds.Add(f);
            }
        }

        public ICommand SaveSelectedFeedsCommand
        {
            get {return _saveAndContinueCommand;}
        }

        public ICommand CancelCommand
        {
            get { return _cancelCommand; }
        }
    }
}
